package reflact;


import java.lang.reflect.Field;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 江岸
 * @version V1.0
 * @ClassName: DemoCode
 * @description: TODO
 * @date 2021/4/129:17
 * @since V1.0
 */
public class DemoCode {

    public ThreadLocal<String> t = new ThreadLocal<>();
    public Object OBJ = new Object();

    public static void main(String[] args) {
        new DemoCode().fun();
//        User user = new User();
//        user.setUserName("ok");
//        try {
//            Field userName = user.getClass().getDeclaredField("userName");
//            userName.setAccessible(true);
//            System.out.println(userName.get(user));
//        } catch (NoSuchFieldException e) {
//
//
//        } catch (IllegalAccessException e) {
//            e.printStackTrace();
//        }
    }

    public void fun() {
        t.set("main");
        System.out.println("main" + t.get());
        new Thread(() -> {
            t.set("test1");
            for (int i = 0; i < 6; i++) {
                if (i == 3) {
                    t = null;
                    System.out.println("把thread置为空");
                }
                if (i == 4) {
                    //gc之后 会发现下面value有值，但是key为null
                    System.gc();
                    System.out.println("gc操作");
                }
                //System.out.println(t.get() + Thread.currentThread().getName());
                synchronized (OBJ) {
                    try {
                        OBJ.notify();
                        OBJ.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main" + t.get());
        new Thread(() -> {
            t.set("test2");
            for (int i = 0; i < 5; i++) {
                try {
                    Thread thread = Thread.currentThread();
                    Field threadLocals = thread.getClass().getDeclaredField("threadLocals");
                    threadLocals.setAccessible(true);
                    Object map = threadLocals.get(thread);
                    Field table = map.getClass().getDeclaredField("table");
                    table.setAccessible(true);
                    Object o = table.get(map);
                    //反射对象是否数组
                    if (o.getClass().isArray()) ;
                    {
                        System.out.println("+++++++++++++++++++++++++++++++++++++");
                        //探测出10是下标
//                        for (int x=0;x<16;x++){
//                            Object o1 = Array.get(o, x);
//                            System.out.println("x:"+x+o1);
//                        }
                        //反射从线程map的entry中获取value
                        Object entry = Array.get(o, 10);
                        Field value = entry.getClass().getDeclaredField("value");
                        value.setAccessible(true);
                        Object o1 = value.get(entry);
                        Method get = entry.getClass().getMethod("get", null);
                        ThreadLocal invoke = (ThreadLocal) get.invoke(entry);
                        //referent.setAccessible(true);
                        System.out.println(o1 + "value值");
                        //在置为空之后，这里的map中key使用弱引用仍旧可以拿到threadLocal对
                        //但gc之后这里的key也会没有
                        System.out.println(invoke + "key值");
                        System.out.println(invoke.get() + "用key获取value");
                    }
                } catch (NoSuchFieldException e) {


                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                //当在test1中的第三次循环把threadLocal对象置为空之后，在test2的map中还保存有entry值，引申内存泄漏的内容
                //System.out.println(t.get() + Thread.currentThread().getName());
                synchronized (OBJ) {
                    try {
                        OBJ.notify();
                        OBJ.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            OBJ.notify();
        }).start();

    }


    class RunTest implements Runnable {

        @Override
        public void run() {
            t.set("ff");
        }
    }
}